package com.hp.bon.sgw.service;

import com.google.gson.Gson;
import com.hp.bon.sgw.bean.DCCMsgModifyBean;
import com.hp.bon.sgw.start.SpringContext;
import com.hp.bon.sgw.util.dcc.DccAvpHelper;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.AVP_UTF8String;
import com.hp.ocs.diameter.message.Message;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Path("/")
public class DCCMsgModfyService
  implements ConfigListener
{
  private static DCCMsgModfyService instance;
  private static final Logger logger = LoggerFactory.getLogger(DCCMsgModfyService.class);
  private volatile boolean enabled = false;
  private volatile List<DCCMsgModifyBean> allModifyBeans = Collections.emptyList();
  private Set<String> monitorConfKeys = new HashSet(1);
  private static String enabledKey = "sgw.dcc.modify.enabled";
  private String dccModiyRulesFile = "./etc/dcc-modify-rules.json";

  public static DCCMsgModfyService getInstance()
  {
    if (instance == null) {
      instance = new DCCMsgModfyService();
      instance.init();
    }
    return instance;
  }

  public boolean isEnabled()
  {
    return this.enabled;
  }

  public DCCMsgModfyService() {
    this.monitorConfKeys.add(enabledKey);
  }

  public void doModifyDCCMsg(Message msg, boolean isCCR, int direction, String srvCtxID) {
    if (this.allModifyBeans.isEmpty()) {
      return;
    }
    if (srvCtxID == null) {
      AVP avp = msg.find(461);
      if (avp == null) {
        if (logger.isDebugEnabled()) {
          logger.debug("no service context id found ,ignore modify action");
        }
        return;
      }
      srvCtxID = new AVP_UTF8String(avp).queryValue();
    }
    List<DCCMsgModifyBean> curModifBeans = this.allModifyBeans;

    for (DCCMsgModifyBean modBean : curModifBeans) {
      boolean matched = (modBean.getSrvCtxPatten().equals("*")) || (srvCtxID.contains(modBean.getSrvCtxPatten()));
      boolean srvCtxIDMatched = modBean.isExclude() ? true : matched ? false : matched;

      if ((modBean.isCcr() == isCCR) && (modBean.getDirection() == direction) && (srvCtxIDMatched)) {
        logger.info("matched dcc msg modify rule for " + srvCtxID + " ,rule name:" + modBean.getName());
        try {
          modifyMsg(msg, modBean);
        } catch (Exception e) {
          logger.warn("modify dcc msg err:" + e);
        }
      }
    }
  }

  private void modifyMsg(Message msg, DCCMsgModifyBean modBean) throws Exception {
    switch (modBean.getAct()) {
    case 1:
      DccAvpHelper.moveUpServiceInfomationAVP(msg, modBean.getSourceAvp());
      return;
    case 2:
      DccAvpHelper.moveIntoServiceInfomationAVP(msg, modBean.getSourceAvp());
      return;
    case 3:
      DccAvpHelper.changeServiceInfomationAVP(msg, modBean.getSourceAvp(), modBean.getTargetAvpName(), modBean.getExpression());
      return;
    }
  }

  public void init()
  {
    readEnabledKey();
    reloadDCCMsgModifyRules();
  }
  @GET
  @Path("config/reloadccrules/")
  @Produces({"text/html"})
  public String reloadDCCMsgModifyRules() { String inf = "load dcc msg modify rules from file " + this.dccModiyRulesFile;
    logger.info(inf);
    String errMsg = "";
    LineNumberReader reader = null;
    LinkedList rules = new LinkedList();
    try {
      reader = new LineNumberReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(this.dccModiyRulesFile)), "utf-8"));
      String line = null;
      while ((line = reader.readLine()) != null) {
        if (!"".equals(line.trim())) {
          DCCMsgModifyBean rule = (DCCMsgModifyBean)new Gson().fromJson(line, DCCMsgModifyBean.class);
          rules.add(rule);
        }
      }
      this.allModifyBeans = rules;
    } catch (Exception e) {
      errMsg = e.toString();
      logger.warn("caught err" + e);

      if (reader != null)
        try {
          reader.close();
        } catch (IOException e1) {
          logger.warn("caught err" + e1);
        }
    }
    finally
    {
      if (reader != null) {
        try {
          reader.close();
        } catch (IOException e) {
          logger.warn("caught err" + e);
        }
      }
    }
    return inf + " " + errMsg;
  }

  public Set<String> monitorConfKeys()
  {
    return this.monitorConfKeys;
  }

  public void onConfigUpdated(String updatedKey)
  {
    if (updatedKey.equals(enabledKey))
      readEnabledKey();
  }

  public void setDccModiyRulesFile(String dccModiyRulesFile)
  {
    this.dccModiyRulesFile = dccModiyRulesFile;
  }

  private void readEnabledKey() {
    int value = SpringContext.getInstance().getConfigService().getIntValue(enabledKey, 0);
    this.enabled = (value == 1);
    logger.info("dcc msg modify is enabled :" + this.enabled);
  }
}